package com.common.service.judicialcheck.impl;

import com.common.constants.Constants;
import com.common.converter.JudicialCheckConverter;
import com.common.entity.judicialcheck.JudicialCheckEntity;
import com.common.entity.judicialcheck.QJudicialCheckEntity;
import com.common.entity.target.QTargetItemEntity;
import com.common.entity.target.TargetTypeEntity;
import com.common.global.BizException;
import com.common.global.BizServiceEnum;
import com.common.global.CommonEnum;
import com.common.query.QueryConditionVo;
import com.common.repository.judicialcheck.JudicialCheckRepository;
import com.common.repository.target.TargetTypeRepository;
import com.common.requestvo.judicialcheck.JudicialCheckFillCountReqVo;
import com.common.requestvo.judicialcheck.JudicialCheckReqVo;
import com.common.requestvo.target.TargetItemAssignReqVo;
import com.common.service.judicialcheck.JudicialCheckService;
import com.common.service.target.TargetItemService;
import com.common.service.target.TargetTypeService;
import com.common.vo.DateUtils;
import com.common.vo.judicialcheck.JudicialCheckVo;
import com.common.vo.target.TargetItemVo;
import com.common.vo.target.TargetTypeVo;
import com.querydsl.core.QueryResults;
import com.querydsl.core.Tuple;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author johnny
 * @create 2021-05-15 5:26 下午
 **/
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class JudicialCheckServiceImpl implements JudicialCheckService {


    private final TargetTypeRepository targetTypeRepository;

    private final JudicialCheckRepository judicialCheckRepository;

    private final JPAQueryFactory queryFactory;

    public JudicialCheckServiceImpl(TargetTypeRepository targetTypeRepository, JudicialCheckRepository judicialCheckRepository, JPAQueryFactory queryFactory) {
        this.targetTypeRepository = targetTypeRepository;
        this.judicialCheckRepository = judicialCheckRepository;
        this.queryFactory = queryFactory;
    }

    /**
     * 初始化 数据
     * //主要逻辑就是
     *
     * @param targetItemAssignReqVo
     */
    @Override
    public void initJudicialCheck(TargetItemAssignReqVo targetItemAssignReqVo) {
        Long count = judicialCheckRepository.countByPersonalIdAndYearAndMonth(targetItemAssignReqVo.getPersonalId(), targetItemAssignReqVo.getYear(),
                targetItemAssignReqVo.getMonth());

        if (count > 0) {
            //删除 检察官业绩考核指标记录
            judicialCheckRepository.deleteByPersonalIdAndYearAndMonth(targetItemAssignReqVo.getPersonalId(), targetItemAssignReqVo.getYear(),
                    targetItemAssignReqVo.getMonth());
        }
        List<TargetItemVo> targetItemVos = targetItemAssignReqVo.getTargetItemVos();
        if (CollectionUtils.isNotEmpty(targetItemVos)) {
            List<JudicialCheckEntity> list = new ArrayList<>();

            targetItemVos.forEach(targetItemVo -> {
                if (targetItemVo.getTargetSuperTypeId() == null) {
                    return;
                }
                if (judicialCheckRepository.countByPersonalIdAndYearAndMonthAndTargetItemId(targetItemAssignReqVo.getPersonalId(),
                        targetItemAssignReqVo.getYear(), targetItemAssignReqVo.getMonth(), targetItemVo.getId()) > 0) {
                    judicialCheckRepository.deleteByPersonalIdAndYearAndMonthAndTargetItemId(targetItemAssignReqVo.getPersonalId(),
                            targetItemAssignReqVo.getYear(), targetItemAssignReqVo.getMonth(), targetItemVo.getId());
                }
                JudicialCheckEntity judicialCheckEntity = new JudicialCheckEntity();
                judicialCheckEntity.setPersonalId(targetItemAssignReqVo.getPersonalId());
                judicialCheckEntity.setCount(0L);
                judicialCheckEntity.setMonth(targetItemAssignReqVo.getMonth());
                judicialCheckEntity.setYear(targetItemAssignReqVo.getYear());
                String date = targetItemAssignReqVo.getYear() + "-" + targetItemAssignReqVo.getMonth();
                Date dateTime = DateUtils.formatDate(date, "yyyy-MM");
                judicialCheckEntity.setDataTime(dateTime);
                judicialCheckEntity.setPersonalName(targetItemAssignReqVo.getPersonalName());
                judicialCheckEntity.setTargetItemId(targetItemVo.getId());
                //绑定 super 父类ID  如 效果 id  效率 id 等这种大类型id ， 为了后期页面 上根据不同的 super大类型进行查询
                // targetItemVo.getTargetSuperTypeId 是在导入指标的时候 绑定的 super 父id
                judicialCheckEntity.setTargetSuperTypeId(targetItemVo.getTargetSuperTypeId());
                judicialCheckEntity.setDepartmentId(targetItemAssignReqVo.getDepartmentId());
                //judicialCheckEntity.setTargetItemName(targetItemVo.getTargetItemName());
                judicialCheckEntity.setScore(new BigDecimal(0));
                judicialCheckEntity.setCreateBy(targetItemAssignReqVo.getUpdateBy());
                list.add(judicialCheckEntity);
            });
            //保存 人员的 待考核记录表
            judicialCheckRepository.saveAll(list);
        }

    }

    @Override
    public void deleteJudicialCheck(Long personalId, Integer year, Integer month) {
        judicialCheckRepository.deleteByPersonalIdAndYearAndMonth(personalId, year, month);
    }

    @Override
    public Page<JudicialCheckVo> listByCondition(JudicialCheckReqVo judicialCheckReqVo, Pageable pageable) {


        if (StringUtils.isEmpty(judicialCheckReqVo.getTargetTypeName())) {
            throw new BizException(BizServiceEnum.CAN_NOT_NULL_SUPER_TARGET_TYPE);
        }
        if (!Constants.FILL_JUDICIAL_CHECK_SUPER_TYPE_SET.contains(judicialCheckReqVo.getTargetTypeName())) {
            throw new BizException(BizServiceEnum.CAN_NOT_NULL_SUPER_TARGET_TYPE);
        }

        TargetTypeEntity typeEntity = targetTypeRepository.findByName(judicialCheckReqVo.getTargetTypeName());
        if (typeEntity == null) {
            throw new BizException(BizServiceEnum.CAN_NOT_FIND_SUPER_TARGET_TYPE);
        }


        List<JudicialCheckVo> list = new ArrayList<>();
        QJudicialCheckEntity qJudicialCheckEntity = QJudicialCheckEntity.judicialCheckEntity;
        QTargetItemEntity qTargetItemEntity = QTargetItemEntity.targetItemEntity;

        JPAQuery<Tuple> jpaQuery = queryFactory.select(qJudicialCheckEntity, qTargetItemEntity.targetItemName)
                .from(qJudicialCheckEntity)
                .leftJoin(qTargetItemEntity).on(qTargetItemEntity.id.eq(qJudicialCheckEntity.targetItemId))
                .where(qJudicialCheckEntity.targetSuperTypeId.eq(typeEntity.getId()))
                .offset(pageable.getPageNumber() * pageable.getPageSize())
                .limit(pageable.getPageSize());

        fillCondition(jpaQuery, judicialCheckReqVo);

        QueryResults<Tuple> queryResults = jpaQuery.fetchResults();

        queryResults.getResults().forEach(tuple -> {
            JudicialCheckEntity judicialCheckEntity = tuple.get(0, JudicialCheckEntity.class);
            String targetItemName = tuple.get(1, String.class);
            JudicialCheckVo judicialCheckVo = JudicialCheckConverter.INSTANCE.domain2vo(judicialCheckEntity);
            judicialCheckVo.setTargetItemName(targetItemName);
            list.add(judicialCheckVo);
        });
        return new PageImpl<>(list, pageable, queryResults.getTotal());
    }

    /**
     * 填表 方法
     *
     * @param judicialCheckFillCountReqVo : 填表项数据
     */
    @Override
    public void fillJudicialCheckCount(JudicialCheckFillCountReqVo judicialCheckFillCountReqVo) {
        if (judicialCheckFillCountReqVo.getId() == 0L) {
            throw new BizException(CommonEnum.ID_NOT_NULL);
        }
        JudicialCheckEntity judicialCheckEntity = judicialCheckRepository.findById(judicialCheckFillCountReqVo.getId()).orElse(null);
        if (judicialCheckEntity == null) {
            throw new BizException(CommonEnum.ID_NOT_FIND_ENTITY);
        }
        judicialCheckEntity.setCount(judicialCheckFillCountReqVo.getCount());
        judicialCheckEntity.setUpdateBy(judicialCheckFillCountReqVo.getUpdateBy());
        judicialCheckRepository.save(judicialCheckEntity);
    }


    private void findChildrenIds(List<TargetTypeVo> children, List<Long> allIds) {
        allIds.addAll(children.stream().map(TargetTypeVo::getId).collect(Collectors.toList()));
        children.forEach(targetTypeVo -> {
            if (CollectionUtils.isNotEmpty(targetTypeVo.getChildren())) {
                findChildrenIds(targetTypeVo.getChildren(), allIds);
            }
        });
    }

    @Override
    public void fillCondition(JPAQuery<Tuple> jpaQuery, QueryConditionVo queryConditionVo) {
        JudicialCheckReqVo judicialCheckReqVo = (JudicialCheckReqVo) queryConditionVo;
        QJudicialCheckEntity qJudicialCheckEntity = QJudicialCheckEntity.judicialCheckEntity;
        QTargetItemEntity qTargetItemEntity = QTargetItemEntity.targetItemEntity;
        if (judicialCheckReqVo.getYear() != null && judicialCheckReqVo.getYear() != 0) {
            jpaQuery.where(qJudicialCheckEntity.year.eq(judicialCheckReqVo.getYear()));
        }
        if (judicialCheckReqVo.getMonth() != null && judicialCheckReqVo.getMonth() != 0) {
            jpaQuery.where(qJudicialCheckEntity.month.eq(judicialCheckReqVo.getMonth()));
        }
        if (StringUtils.isNotEmpty(judicialCheckReqVo.getTargetItemName())) {
            jpaQuery.where(qTargetItemEntity.targetItemName.like("%" + judicialCheckReqVo.getTargetItemName() + "%"));
        }
        if (judicialCheckReqVo.getPersonalId() != null && judicialCheckReqVo.getPersonalId() != 0L) {
            //账号登录进来 需要查看当前账号 所需要填写的 指标项 所以要绑定 personalId 查询条件
            jpaQuery.where(qJudicialCheckEntity.personalId.eq(judicialCheckReqVo.getPersonalId()));
        }
        if (judicialCheckReqVo.getDepartmentId() != null && judicialCheckReqVo.getDepartmentId() != 0L) {
            jpaQuery.where(qJudicialCheckEntity.departmentId.eq(judicialCheckReqVo.getDepartmentId()));
        }

        String startTime = judicialCheckReqVo.getStartTime();
        String endTime = judicialCheckReqVo.getEndTime();

        if (StringUtils.isNotEmpty(startTime) && startTime.contains("-")) {
            jpaQuery.where(qJudicialCheckEntity.dataTime.goe(DateUtils.formatDate(startTime, "yyyy-MM")));
        }
        if (StringUtils.isNotEmpty(endTime)) {
            jpaQuery.where(qJudicialCheckEntity.dataTime.loe(DateUtils.formatDate(endTime, "yyyy-MM")));
        }
    }
}